package com.lkc.aspect;

import com.lkc.annotation.LogMethod;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

@Component
@Aspect
public class DZAspect {

    @Pointcut("@annotation(com.lkc.annotation.LogMethod)")
    public void logmethod() {
        // 切点方法体为空，仅用于定义切点表达式
    }

    @Around("logmethod() && @annotation(logMethod)")
    public Object logMethod(ProceedingJoinPoint point, LogMethod logMethod) throws Throwable {
        long startTime = System.currentTimeMillis();
        StringBuilder logBuilder = new StringBuilder();

        // 获取方法信息
        String serviceName = logMethod.serviceName();
        boolean recordParam = logMethod.recordParam();
        boolean recordReturn = logMethod.recordReturn();
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        String methodName = methodSignature.getMethod().getName();

        // 构建基础日志信息
        logBuilder.append("[").append(serviceName).append("] ")
                .append("method:(").append(methodName).append(") ");

        // 记录参数
        if (recordParam) {
            logBuilder.append("param:").append(formatArgs(point.getArgs())).append(" ");
        }

        Object result = null;
        Throwable throwable = null;

        // 执行目标方法
        try {
            result = point.proceed();
            return result;
        } catch (Throwable t) {
            throwable = t;
            throw t;
        } finally {
            long endTime = System.currentTimeMillis();
            long executeTime = endTime - startTime;

            // 记录返回值或异常
            if (recordReturn && throwable == null) {
                logBuilder.append("return:").append(result).append(" ");
            }

            if (throwable != null) {
                logBuilder.append("exception:").append(throwable.getClass().getSimpleName())
                        .append(":").append(throwable.getMessage()).append(" ");
            }

            // 记录执行时间
            logBuilder.append("time:[").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))
                    .append("] executeTime:").append(executeTime).append("ms");

            // 输出日志
            System.out.println(logBuilder.toString());
        }
    }

    /**
     * 格式化参数
     */
    private String formatArgs(Object[] args) {
        if (args == null || args.length == 0) {
            return "()";
        }

        StringBuilder sb = new StringBuilder("(");
        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                sb.append(", ");
            }

            // 对于密码等敏感信息可以进行特殊处理
            if (args[i] != null && args[i].toString().toLowerCase().contains("password")) {
                sb.append("***");
            } else if (args[i] == null) {
                sb.append("null");
            } else {
                // 限制输出长度，避免日志过长
                String argStr = args[i].toString();
                if (argStr.length() > 100) {
                    sb.append(argStr.substring(0, 100)).append("...");
                } else {
                    sb.append(argStr);
                }
            }
        }
        sb.append(")");
        return sb.toString();
    }
}
